#include	"alp_global_vars.h"
#include	"config_parser.h"

int PACK_ID = 0, nextProp = 0, propLIMIT = -1;
bool currentFilled = false;
int msg_counter = 0;
proposer_msg *p_msg;

void generate_instance(proposer_msg *pm) {
	memcpy(&data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].packet.p_msgs[0], pm, sizeof(proposer_msg));
	msg_counter = 0;
	propLIMIT = alp_interval_performance->next_instance_id;
	PACK_ID++;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].packet.pack_id = PACK_ID;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].deliver = false;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].received = false;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].instance_id = alp_interval_performance->next_instance_id;
	assert(data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].packet.pack_id == alp_interval_performance->next_instance_id + 1);
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].coordinator_id = COORDINATOR_ID;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].dec = -1;
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].round_number = 1;// =0
	data[(alp_interval_performance->next_instance_id % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].packet.p_msgs[0].num_nodes_visited++;

	alp_interval_performance->next_instance_id++;
	alp_interval_performance->total_num_instances++;
}

void prepare_fresh_instances_timer_event(int sd, short event, void * arg) {

	//	alp_interval_performance->interval_num_entrance++;

	int counter = 0;
	//	while (counter < SUBMIT_PER_WAKE && nextProp <= propLIMIT) {
	if (nextProp <= propLIMIT) {

		data[(nextProp % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].highestDeliverable = alp_interval_performance->highest_deliverable_inst_id;
		data[(nextProp % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].received = true;

		if (data[(nextProp % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers))].packet.p_msgs[0].num_nodes_visited < get_config_info()->ring_size)
			send_inst_paxos_to_successor((nextProp % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers)));
		else
			send_short_paxos_to_successor((nextProp % (INTERNAL_BUFFER_SIZE * get_config_info()->total_num_proposers)));

		//gapEnd = nextProp;
		alp_interval_performance->interval_num_packets_sent++;
		counter++;
		nextProp++;
	}
	//	}

	//	evtimer_add(inst_propose_timeout_eve, &tv3);
}
void send_inst_paxos_to_successor(int nextMulticast) {
	rtag = true;
	inst_paxos inst_paxos_msg;

	inst_paxos_msg.inst_packet = data[nextMulticast];
	inst_paxos_msg.inst_packet.received = false;
	inst_paxos_msg.type = 'n';

	//	if (inst_paxos_msg.inst_packet.packet.p_msgs[0].msg_id != 0)
	coordinator_execute_phase_2_a(inst_paxos_msg.inst_packet.instance_id, inst_paxos_msg.inst_packet.round_number, &inst_paxos_msg.paxos_2b);
	inst_paxos_msg.inst_packet.highestDeliverable = alp_interval_performance->highest_deliverable_inst_id;
	assert(inst_paxos_msg.inst_packet.instance_id + 1 == inst_paxos_msg.inst_packet.packet.pack_id);

	int status = send((get_config_info()->server_infos[get_config_info()->self_acceptor_id].successor_sid), &inst_paxos_msg, sizeof(inst_paxos), MSG_WAITALL);
	assert(status == sizeof(inst_paxos));
	alp_interval_performance->interval_bytes_sent += status;
}

void send_short_paxos_to_successor(int nextMulticast) {
	rtag = true;
	paxos_short_not pd_msg;
	pd_msg.type = 'm';
	//if (data[nextMulticast].packet.p_msgs[0].msg_id != 0)
	coordinator_execute_phase_2_a(data[nextMulticast].instance_id, data[nextMulticast].round_number, &pd_msg.paxos_2b);

	pd_msg.short_decision.highestDeliverable = alp_interval_performance->highest_deliverable_inst_id;
	pd_msg.short_decision.instance_id = data[nextMulticast].instance_id;
	pd_msg.short_decision.pack_id = data[nextMulticast].packet.pack_id;
	pd_msg.short_decision.proposer_id = data[nextMulticast].packet.p_msgs[0].proposer_id;
	pd_msg.short_decision.location_index_in_proposer = data[nextMulticast].packet.p_msgs[0].location_index_in_proposer;
	assert(pd_msg.short_decision.instance_id + 1 == pd_msg.short_decision.pack_id);
	pd_msg.short_decision.proposer_msg_id = data[nextMulticast].packet.p_msgs[0].msg_id;
	pd_msg.short_decision.type = 's';

	int status = send((get_config_info()->server_infos[get_config_info()->self_acceptor_id].successor_sid), &pd_msg, sizeof(paxos_short_not), MSG_WAITALL);
	assert(status == sizeof(paxos_short_not));
	alp_interval_performance->interval_bytes_sent += status;

}
